package arena.soldier;

import gameframework.base.Drawable;
import gameframework.base.MoveStrategy;
import gameframework.base.Overlappable;
import gameframework.game.GameEntity;
import gameframework.game.GameMovable;
import gameframework.game.GameMovableDriverDefaultImpl;

import java.awt.Canvas;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;
import java.lang.reflect.Method;

import java.util.ArrayList;
import java.util.List;

import arena.base.HeroMoveStrategy;
import arena.utils.*;

public class ArmedUnitSoldier extends GameMovable implements Drawable, GameEntity, Overlappable, ArmedUnit{
	protected Soldier soldier;
	protected List<String> equipments = new ArrayList<String>();
	protected AgeFactory age;
	
	protected boolean movable = true;
	protected boolean active = true;
	public static final int RENDERING_SIZE = 36;
	
	private ArrayList<Observer<?>> observers = new ArrayList<Observer<?>>();

	public ArmedUnitSoldier(AgeFactory factory, String soldatType, String name, Canvas defaultCanvas) {
		this.age = factory;
		soldier = age.getSimpleSoldier("Wolf", defaultCanvas);
	}
	
	public void addEquipment(String equipmentType) {
		if (alive()) { // XXX "else" not treated
			if (equipments.contains(equipmentType)) {
				return; // decoration not applied
			} else {
				String methodName = "get" + equipmentType + "Weapon";
				try {
					Method method = age.getClass().getMethod(methodName,
							Soldier.class);
					soldier = (Soldier) method.invoke(age, soldier);
					equipments.add(equipmentType);
				} catch (Exception e) {
					throw new RuntimeException("Unknown equipment type "
							+ e.toString());
				}
			}
		}
	}

	public String getName() {
		return soldier.getName();
	}

	public float getHealthPoints() {
		return soldier.getHealthPoints();
	}

	public AgeFactory getAge() {
		return age;
	}

	public boolean alive() {
		return soldier.alive();
	}

	public void heal() {
		soldier.heal();
	}

	public float strike() {
		return soldier.strike();
	}

	public boolean parry(float force) {
		return soldier.parry(force);
	}

	@Override
	public Rectangle getBoundingBox() {
		return (new Rectangle(0, 0, RENDERING_SIZE, RENDERING_SIZE));
	}

	@Override
	public void oneStepMoveAddedBehavior() {		
		((GameMovable) soldier).oneStepMoveAddedBehavior();
	}

	@Override
	public void draw(Graphics g) {		
		soldier.draw(g);		
	}
	
	public void setDriver(GameMovableDriverDefaultImpl driver){
		((GameMovable) soldier).setDriver(driver);
	}
	
	public void oneStepMove(){
		((GameMovable) soldier).oneStepMove();
	}
	
	public void setPosition(Point p){
		((GameMovable) soldier).setPosition(p);
	}
	
	public void setMoveStrategy(MoveStrategy keyStr) {
		((ArmedUnitSoldier) soldier).setMoveStrategy(keyStr);
	}
	
	public HeroMoveStrategy getMoveStrategy() {
		return ((ArmedUnitSoldier) soldier).getMoveStrategy();
	}
	
	public Point getPosition(){
		return soldier.getPosition();
	}
	
	public boolean isEnrage() {		
	   return  soldier.isEnrage();
	}

	public void setEnrage(int timer) {
		soldier.setEnrage(timer);
	}	
	
	public void register(Observer<?> ob) {
		observers.add(ob);
	}

	public void unregister(Observer<?> ob) {
		observers.remove(ob);
	}

	public void notify(ArmedUnit s) {
		for (Observer<?> ob : observers)
			ob.update(s);
	}

	@Override
	public boolean receiveAttack(float force) {
		if (force > soldier.getHealthPoints()){
			return true;
		}
		else{
		this.soldier.setHealthPoints(soldier.getHealthPoints()-force);
		return false;
		}
	}
}
